package org.vectrics.location;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.vectrics.common.db.RecordObject;
import org.vectrics.domain.Domain;

/**
 * A Location - hierarchical categorizations of locations in the world.
 * 
 * @author M.J.M.
 * @version $Revision: 1.4 $ $Date: 2006/04/15 18:04:01 $
 */
public class Location implements Serializable, RecordObject, Comparable<Location> {

    public static final String CITY = "city";

    public static final String STATE = "state";

    public static final String COUNTRY = "country";

    public static final long serialVersionUID = 34534555;

    private Long id;

    private Domain domain = null;

    private Location parent;

    private String name;

    private String description;

    private String abbreviation;

    private String typeCode;

    private boolean voided = false;

    private boolean approved = false;

    private Set<Location> children = new HashSet<Location>();

    /**
     * @return Returns the id.
     */
    public Long getId() {
        return id;
    }

    /**
     * @param id
     *            The id to set.
     */
    public void setId(final Long id) {
        this.id = id;
    }

    @Override
    public boolean equals(final Object other) {
        Location otherLocation = (Location) other;
        return toString().equals(otherLocation.toString());
    }

    /**
     * The domain to which this location belongs. A location with a domain is
     * used by that domain and all children of that domain.
     * 
     * @return
     */
    public Domain getDomain() {
        return domain;
    }

    public void setDomain(final Domain domain) {
        this.domain = domain;
    }

    public String getName() {
        return name;
    }

    public void setName(final String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(final String description) {
        this.description = description;
    }

    public Set<Location> getBranchChildren() {
        Set<Location> branchChildren = new HashSet<Location>();
        Iterator<Location> iter = getChildren().iterator();
        while (iter.hasNext()) {
            Location location = iter.next();
            branchChildren.add(location);
            branchChildren.addAll(location.getBranchChildren());
        }
        return branchChildren;
    }

    /**
     * @return Returns the parent.
     */
    public Location getParent() {
        return parent;
    }

    /**
     * @param parent
     *            The parent to set.
     */
    public void setParent(final Location parent) {
        this.parent = parent;
        if (parent != null) {
            // parent.getChildren().add(this);
        }
    }

    /**
     * @return Returns the typeCode.
     */
    public String getTypeCode() {
        return typeCode;
    }

    /**
     * @param typeCode
     *            The typeCode to set.
     */
    public void setTypeCode(final String typeCode) {
        this.typeCode = typeCode;
    }

    public Location addChild() {
        Location location = new Location();
        getChildren().add(location);
        location.setParent(this);
        return location;
    }

    /**
     * @return Returns the childrean.
     */
    public Set<Location> getChildren() {
        return children;
    }

    /**
     * @param childrean
     *            The childrean to set.
     */
    public void setChildren(final Set<Location> children) {
        this.children = children;
    }

    /**
     * @return Whether this location has been approved by qualified person. If
     *         this location was added by someone without qualification, this
     *         location needs to be approved before considering it a permanent
     *         part of all locations.
     */
    public boolean getApproved() {
        return approved;
    }

    public void setApproved(final boolean approved) {
        this.approved = approved;
    }

    /**
     * @return Returns the voided.
     */
    public boolean getVoided() {
        return voided;
    }

    /**
     * @param voided
     *            The voided to set.
     */
    public void setVoided(final boolean voided) {
        this.voided = voided;
    }

    /**
     * @return the abbreviation
     */
    public String getAbbreviation() {
        return abbreviation;
    }

    /**
     * @param abbreviation
     *            the abbreviation to set
     */
    public void setAbbreviation(final String abbreviation) {
        this.abbreviation = abbreviation;
    }

    @Override
    public String toString() {
        StringBuffer str = new StringBuffer();
        str.append("id=" + getId());
        str.append("|name=" + getName());
        str.append("|typeCode=" + typeCode);
        str.append("|domain.id=" + domain.getId());
        return str.toString();
    }

    public int compareTo(final Location comparado) {
        return getName().compareToIgnoreCase(comparado.getName());
    }

}
